
package com.tencent.weibo.operation
{
	import com.adobe.serialization.json.JSONDecoder;
	import com.tencent.weibo.log.LevelLogger;
	import com.tencent.weibo.support.WeiboUtil;
	
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	
	import mx.logging.ILogger;
	
	/**
	 * 当数据加载完成，派发这个事件，您可以通过data属性获取数据
	 */
	[Event(name="complete", type="flash.events.Event")]
	/**
	 * 数据加载过程中，派发这个事件，您可以了解加载进度
	 */
	[Event(name="progress", type="flash.events.ProgressEvent")]
	/**
	 * 当数据加载失败，则派发这个事件
	 */
	[Event(name="ioError", type="flash.events.IOErrorEvent")]
	
	/**
	 * 基于FileReference的数据请求封装(用于文件上传)，实现了IRequestOperation接口。参见IRequestOperation的说明:
	 * @copy IRequestOperation
	 * @langversion 3.0
	 * @playerversion Flash 9
	 * @playerversion AIR 1.1
	 */	
	public class FileRequestOperation extends EventDispatcher implements IRequestOperation
	{
		/**
		 * 日志输出对象
		 */		
		public static var logger:ILogger = LevelLogger.getLogger("com.tencent.weibo.operation.FileRequestOperation");
		/**@private*/
		private var _service:FileReference;
		/**@private*/
		private var url:String;
		/**@private*/
		private var parms:Object;
		/**@private*/
		private var method:String;
		/**@private*/
		private var format:String;
		/**@private*/
		private var _data:Object;
		/**@private*/
		private var request:URLRequest;
		/**@private*/
		private var attachFileParm:String;
		/**
		 * @copy IRequestOperation#data
		 * @return 数据对象
		 */		
		public function get data():Object
		{
			return _data;
		}
		/**
		 * @copy IRequestOperation#service
		 * @return service对象
		 */		
		public function get service():Object
		{
			return _service;
		}
		/**
		 * 不要在外部对service赋值，这个实例只能由类内部产生
		 * @param value
		 */		
		public function set service(value:Object):void
		{
			throw new Error("don't set service property to URLRequestOperation");
		}
		/**
		 * 从URL字符串匹配当前调用的API名称
		 * @return 
		 * 
		 */		
		public function get apiName():String
		{
			var leftChar:String = url.split("?")[0];
			var charArr:Array = leftChar.split("/");
			var endChar:String = charArr[charArr.length-2]+"/"+charArr[charArr.length-1];
			return endChar;
		}
		/**
		 * 获取数据格式
		 * @return 
		 */		
		public function get dataFormat():String
		{
			return format;
		}
		/**
		 * 构造方法
		 * @param url API请求的网络地址
		 * @param parms 用户调用API传入的参数
		 * @param format 返回的数据格式，默认是字符串，支持json和xml
		 * @param file 文件引用
		 * @param attachFileParm 文件域表单名
		 */		
		public function FileRequestOperation(url:String,parms:Object,format:String="string",attachFileParm:String="Filedata",file:FileReference=null)
		{
			this.url = url;
			this.parms = parms;
			this.format = format.toLowerCase();
			this.attachFileParm = attachFileParm;
			var paramsString:String = WeiboUtil.parseObj2URLString(parms);
			_service = file;
			//FIXME:这里如果不传递URL参数，会导致验证失败，原因不明
			request = new URLRequest(url+"?"+paramsString);
			request.data = paramsString;
			request.method = "POST";
			configureListeners();
			_service.upload(request,attachFileParm);
		}
		/**@private*/
		private function configureListeners():void 
		{
			_service.addEventListener(ProgressEvent.PROGRESS,progressHandler);
			_service.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
			_service.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,uploadCompleteDataHandler);
		}
		/**@private*/
		private function removeListeners():void 
		{
			_service.removeEventListener(ProgressEvent.PROGRESS,progressHandler);
			_service.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
			_service.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA,uploadCompleteDataHandler);
		}
		
		/**@private*/
		protected function errorHandler(event:IOErrorEvent):void
		{
			dispatchEvent(event);
			_service.removeEventListener(IOErrorEvent.IO_ERROR,errorHandler);
		}
		
		/**@private*/
		protected function progressHandler(event:ProgressEvent):void
		{
			dispatchEvent(event);
		}
		
		/**@private*/
		protected function uploadCompleteDataHandler(event:DataEvent):void
		{
			var sourceData:String = event.data;
			switch(format)
			{
				case "json":
					try
					{
						_data = new JSONDecoder(sourceData).getValue();
					}
					catch(err:Error)
					{
						logger.error("completeHandler:JSON format unusual: {0}",err.message);
						return;
					}
					break;
				case "xml":
					if(sourceData.indexOf("<") != -1 && sourceData.indexOf(">") != -1)
					{
						try
						{
							_data = new XML(sourceData);
						}
						catch(err:Error)
						{
							logger.error("completeHandler:XML format unusual: {0}",err.message);
							return;
						}
					}
					else
					{
						format = "json";
						uploadCompleteDataHandler(event);
						return;
					}
					break;
				default:
					_data = sourceData;
			}
			dispatchEvent(new Event(Event.COMPLETE));
			removeListeners();
		}
		/**
		 * 文件选择时的图片过滤
		 * @return FileFilter
		 */		
		public static function getImageTypeFilter():FileFilter 
		{
			return new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png");
		}
		
		/**
		 * 重复调用
		 */		
		public function repeat():void
		{
			//do nothing
		}
		
	}
}